home *** CD-ROM | disk | FTP | other *** search
/ Gamers Delight 2 / Gamers Delight 2.iso / Aminet / game / role / AMScen_0_9.lha / AMScen / email.m < prev    next >
Text File  |  1995-01-21  |  14KB  |  578 lines

  1. /*
  2.  * Amiga MUD
  3.  *
  4.  * Copyright (c) 1995 by Chris Gray
  5.  */
  6.  
  7. /*
  8.  * email.m - allow the player to interact with usenet electronic mail.
  9.  */
  10.  
  11. /* NOTE: this current setup is intended for use with Matt Dillon's UUCP
  12.    and mail distribution, version 1.13D or later. To use it with other
  13.    forms of mail, you will perhaps need to change various things.
  14.    Dependencies: UUMAIL: for mail files, T:, sendmail, uuxqt */
  15.  
  16. /* NOTE: this file currently depends on news.m for some player values */
  17.  
  18. /* NOTE: the code here uses the normal place for mail files, i.e. the
  19.    UUMAIL: assign. Thus, you should create a MUD character whose name is
  20.    the same as any names that normally use your system for mail, otherwise
  21.    someone could create them and then would get the outside-of-MUD mail
  22.    intended for that person, and could send out mail seemingly from that
  23.    person. */
  24.  
  25. use t_streets
  26.  
  27. private tp_email CreateTable().
  28. use tp_email
  29.  
  30. define tp_email p_pRunUUXQT CreateBoolProp().
  31. CharacterThing(Character("SysAdmin"))@p_pRunUUXQT := true.
  32.  
  33. define tp_email p_pEmailAliases CreateThingListProp().
  34. define tp_email p_alName CreateStringProp().
  35. define tp_email p_alAddress CreateStringProp().
  36.  
  37. define tp_email p_pEmailTo CreateStringProp().
  38. define tp_email p_pEmailSubject CreateStringProp().
  39. define tp_email p_pEmailString CreateStringProp().
  40.  
  41. define tp_email EmailThing CreateThing(nil).
  42. define tp_email p_EmailParse CreateActionProp().
  43. define tp_email p_EmailLetterParse CreateActionProp().
  44.  
  45. define tp_email g_email CreateGrammar().
  46.  
  47. define tp_email proc mv_help()bool:
  48.     Print(
  49. "Commands in the telegram office are:\n\n"
  50. "  bye/quit - exit from the program\n"
  51. "  exit/leave/out - leave the telegram office\n"
  52. "  info - some additional comments on MUD email\n"
  53. "  read - read your mail\n"
  54. "  name/realname <name> - set your real name to <name>\n"
  55. "  mail <person> [subject] - send a new letter to the given person\n"
  56. "  delete - delete all of your mail\n"
  57. "  alias <name> <address> - create an alias for use with 'mail'\n"
  58. "  alias <name> - delete an alias\n"
  59. "  alias - list all aliases\n"
  60.     );
  61.     true
  62. corp;
  63.  
  64. Verb0(g_email, "help", 0, mv_help).
  65. Synonym(g_email, "help", "?").
  66.  
  67. define tp_email proc mv_info()bool:
  68.  
  69.     Print(
  70. "Your name in the 'name' command can be quoted or not, it doesn't matter. "
  71. "<person> in the 'mail' command must be quoted if the name contains "
  72. "characters other than letters. Remember that the basic parser in use was "
  73. "designed to parse English-language-like input, so it will interpret, e.g.\n"
  74. "   mail fred@big.company.COM\n"
  75. "as 'mail fred @ big' followed by 'company' followed by 'COM'. This is not "
  76. "what you intended. The optional subject on the 'mail' command can be either "
  77. "quoted or not - it depends on whether you put punctuation characters in. "
  78. "You will soon find that using email via MUD is a chore - if you need to do "
  79. "it a lot, you should try to get a normal email connection.\n"
  80.     );
  81.     true
  82. corp;
  83.  
  84. Verb0(g_email, "info", 0, mv_info).
  85.  
  86. VerbTail(g_email, "name", nv_name).
  87. Synonym(g_email, "name", "realname").
  88.  
  89. define tp_email proc emailSendLetter(string s)void:
  90.     int fd;
  91.     string cmd;
  92.     thing me;
  93.  
  94.     me := Me();
  95.     if s = "" then
  96.     Print("Empty letter - not sent.\n");
  97.     else
  98.     /* note: server runs atomically, so no conflict over the temp file */
  99.     fd := FileOpenForWrite("T:MUD.letter");
  100.     if fd = 0 then
  101.         Print("Sorry - can't open letter file.\n");
  102.     else
  103.         Log(me@p_pName + " mailing to " + me@p_pEmailTo + "\n");
  104.         FileWrite(fd, "X-MailSoftware: AmigaMUD telegram office\n");
  105.         FileWrite(fd, "\n");
  106.         FileWrite(fd, s);
  107.         FileClose(fd);
  108.         cmd := "sendmail < T:MUD.letter -f " + FormatName(me@p_pName) +
  109.         " -t " + me@p_pEmailTo;
  110.         if me@p_pEmailSubject ~= "" then
  111.         cmd := cmd + " -s \"" + me@p_pEmailSubject + "\"";
  112.         fi;
  113.         cmd := cmd + " -R \"" + me@p_pNRealName + "\"";
  114.         Execute(cmd);
  115.         Execute("delete T:MUD.letter");
  116.         /* do this so that local mail, as in name@here, will work */
  117.         if CharacterThing(Character("SysAdmin"))@p_pRunUUXQT then
  118.         Execute("uuxqt");
  119.         fi;
  120.     fi;
  121.     fi;
  122.     me -- p_pEmailTo;
  123.     me -- p_pEmailSubject;
  124. corp;
  125.  
  126. define tp_email proc mv_mail()bool:
  127.     thing me, alias;
  128.     string target;
  129.     list thing aliases;
  130.     int count;
  131.     string subject;
  132.  
  133.     target := GetWord();
  134.     if target = "" then
  135.     Print("You must specify an address to mail to.\n");
  136.     false
  137.     else
  138.     me := Me();
  139.     if me@p_pNRealName = "" then
  140.         Print("You cannot email until you have a realname set up.\n");
  141.         false
  142.     else
  143.         aliases := me@p_pEmailAliases;
  144.         if aliases ~= nil then
  145.         count := Count(aliases);
  146.         while count ~= 0 do
  147.             count := count - 1;
  148.             alias := aliases[count];
  149.             if alias@p_alName == target then
  150.             target := alias@p_alAddress;
  151.             fi;
  152.         od;
  153.         fi;
  154.         if target = "" or Index(target, " ") >= 0 then
  155.         Print("Invalid mail target.\n");
  156.         false
  157.         else
  158.         me@p_pEmailTo := target;
  159.         if not CanEdit() then
  160.             Print("To: " + target + "\n");
  161.         fi;
  162.         subject := GetTail();
  163.         if subject ~= "" then
  164.             if SubString(subject, 0, 1) = "\"" then
  165.             subject :=
  166.                 SubString(subject, 1, Length(subject) - 2);
  167.             fi;
  168.             me@p_pEmailSubject := subject;
  169.             if not CanEdit() then
  170.             Print("Subject: ");
  171.             Print(subject);
  172.             Print("\n");
  173.             fi;
  174.         fi;
  175.         GetDocument("email> ", "Enter email letter", "",
  176.                 emailSendLetter, true)
  177.         fi
  178.     fi
  179.     fi
  180. corp;
  181.  
  182. VerbTail(g_email, "mail", mv_mail).
  183.  
  184. define tp_email proc emailAllDone()void:
  185.     thing me;
  186.     int fd;
  187.  
  188.     me := Me();
  189.     fd := me@p_pNFd;
  190.     if fd ~= 0 then
  191.     FileClose(fd);
  192.     me@p_pNFd := 0;
  193.     fi;
  194.     me -- p_pEmailString;
  195.     ignore SetPrompt("telegram office> ");
  196.     ignore SetCharacterInputAction(EmailThing@p_EmailParse);
  197.     ignore SetCharacterIdleAction(me@p_pNSaveIdleHandler);
  198.     me -- p_pNSaveIdleHandler;
  199. corp;
  200.  
  201. define tp_email proc emailFindLetter()bool:
  202.     thing me;
  203.     int fd, colon;
  204.     string line, header;
  205.  
  206.     me := Me();
  207.     if me@p_pEmailString ~= "" then
  208.     true
  209.     else
  210.     fd := me@p_pNFd;
  211.     while
  212.         line := FileRead(fd);
  213.         line ~= "" and Index(line, "From ") ~= 0
  214.     do
  215.     od;
  216.     if line ~= "" then
  217.         me@p_pEmailString := line;
  218.         true
  219.     else
  220.         false
  221.     fi
  222.     fi
  223. corp;
  224.  
  225. define tp_email proc emailShowPage()bool:
  226.     thing me;
  227.     int fd, length, n, width, len;
  228.     string line;
  229.     bool moreLetter;
  230.  
  231.     me := Me();
  232.     fd := me@p_pNFd;
  233.     length := TextHeight(0);
  234.     width := TextWidth(0);
  235.     n := 1;
  236.     line := me@p_pEmailString;
  237.     if line ~= "" then
  238.     me -- p_pEmailString;
  239.     Print(line);
  240.     Print("\n");
  241.     n := 2;
  242.     fi;
  243.     moreLetter := true;
  244.     while
  245.     if n >= length then
  246.         false
  247.     else
  248.         line := FileRead(fd);
  249.         if line = "" then
  250.         moreLetter := false;
  251.         false
  252.         elif Index(line, "From ") = 0 then
  253.         me@p_pEmailString := line;
  254.         moreLetter := false;
  255.         false
  256.         else
  257.         true
  258.         fi
  259.     fi
  260.     do
  261.     Print(line);
  262.     Print("\n");
  263.     len := Length(line);
  264.     if len <= width then
  265.         n := n + 1;
  266.     else
  267.         n := n + (len + width - 4) / (width - 9);
  268.     fi;
  269.     if Index(line, "From: ") = 0 then
  270.         line := SubString(line, 6, Length(line) - 6);
  271.         len := Index(line, " (");
  272.         if len > 0 then
  273.         line := SubString(line, 0, len);
  274.         fi;
  275.         me@p_pEmailTo := line;
  276.     elif Index(line, "Subject: ") = 0 then
  277.         line := SubString(line, 9, Length(line) - 9);
  278.         if line ~= "" then
  279.         me@p_pEmailSubject := "Re: " + line;
  280.         fi;
  281.     fi;
  282.     od;
  283.     moreLetter
  284. corp;
  285.  
  286. define tp_email proc emailSetLetter()void:
  287.  
  288.     ignore SetPrompt("Nrq? ");
  289.     ignore SetCharacterInputAction(EmailThing@p_EmailLetterParse);
  290. corp;
  291.  
  292. define tp_email proc emailMoreParse(string line)void:
  293.  
  294.     if line = "" or line == "c" then
  295.     if not emailShowPage() then
  296.         emailSetLetter();
  297.     fi;
  298.     elif line == "n" then
  299.     if emailFindLetter() then
  300.         if not emailShowPage() then
  301.         emailSetLetter();
  302.         fi;
  303.     else
  304.         emailAllDone();
  305.     fi;
  306.     elif line == "q" then
  307.     emailAllDone();
  308.     else
  309.     Print("Options are:\n"
  310.         "  c - continue reading this letter\n"
  311.         "  n - go on to next letter\n"
  312.         "  q - quit reading mail\n"
  313.         "Empty line is equivalent to 'r'\n"
  314.     );
  315.     fi;
  316. corp;
  317.  
  318. define tp_email proc emailSetMore()void:
  319.  
  320.     ignore SetPrompt("[M O R E] Cnq? ");
  321.     ignore SetCharacterInputAction(emailMoreParse);
  322. corp;
  323.  
  324. define tp_email proc emailLetterParse(string line)void:
  325.     thing me;
  326.  
  327.     me := Me();
  328.     if line == "r" then
  329.     if me@p_pNRealName = "" then
  330.         Print("You cannot email until you have a realname set up.\n");
  331.     else
  332.         if not CanEdit() then
  333.         Print("To: " + me@p_pEmailTo + "\n");
  334.         if me@p_pEmailSubject ~= "" then
  335.             Print("Subject: ");
  336.             Print(me@p_pEmailSubject);
  337.             Print("\n");
  338.         fi;
  339.         fi;
  340.         ignore GetDocument("reply> ", "Enter email reply", "",
  341.                    emailSendLetter, true);
  342.     fi;
  343.     elif line = "" or line == "n" then
  344.     if emailFindLetter() then
  345.         if emailShowPage() then
  346.         emailSetMore();
  347.         fi;
  348.     else
  349.         emailAllDone();
  350.     fi;
  351.     elif line == "q" then
  352.     emailAllDone();
  353.     else
  354.     Print("Options are:\n\n"
  355.         "  r - reply to this letter\n"
  356.         "  n - read next letter\n"
  357.         "  q - quit reading mail\n"
  358.         "Empty line is equivalent to 'n'\n"
  359.     );
  360.     fi;
  361. corp;
  362.  
  363. define tp_email proc emailIdleHandler()void:
  364.     action a;
  365.  
  366.     a := Me()@p_pNSaveIdleHandler;
  367.     emailAllDone();
  368.     call(a, void)();
  369. corp;
  370.  
  371. define tp_email proc mv_read()bool:
  372.     thing me;
  373.     int fd;
  374.     action a;
  375.  
  376.     me := Me();
  377.     fd := FileOpenForRead("UUMAIL:" + me@p_pName);
  378.     if fd = 0 then
  379.     Print("No mail for " + me@p_pName + "\n");
  380.     else
  381.     me@p_pNFd := fd;
  382.     if emailFindLetter() then
  383.         a := SetCharacterIdleAction(emailIdleHandler);
  384.         if a ~= nil then
  385.         me@p_pNSaveIdleHandler := a;
  386.         fi;
  387.         if emailShowPage() then
  388.         emailSetMore();
  389.         else
  390.         emailSetLetter();
  391.         fi;
  392.     else
  393.         Print("Mailbox is invalid - no header found!\n");
  394.     fi;
  395.     fi;
  396.     true
  397. corp;
  398.  
  399. Verb0(g_email, "read", 0, mv_read).
  400.  
  401. define tp_email proc emailParse(string input)void:
  402.     string word;
  403.  
  404.     SetTail(input);
  405.     word := GetWord();
  406.     if word ~= "" then
  407.     if FindAnyWord(g_email, word) ~= 0 then
  408.         ignore Parse(g_email, input);
  409.     else
  410.         ignore Parse(G, input);
  411.     fi;
  412.     fi;
  413. corp;
  414.  
  415. EmailThing@p_EmailParse := emailParse.
  416. EmailThing@p_EmailLetterParse := emailLetterParse.
  417.  
  418. define tp_email proc mv_delete()bool:
  419.  
  420.     Execute("delete UUMAIL:" + Me()@p_pName);
  421.     Print("All mail deleted.\n");
  422.     true
  423. corp;
  424.  
  425. Verb0(g_email, "delete", 0, mv_delete).
  426.  
  427. define tp_email proc mv_alias()bool:
  428.     int count;
  429.     list thing aliases;
  430.     thing alias;
  431.     string name, address;
  432.     bool found;
  433.  
  434.     aliases := Me()@p_pEmailAliases;
  435.     name := GetWord();
  436.     if name = "" then
  437.     if aliases = nil then
  438.         Print("You currently have no email aliases set up.\n");
  439.     else
  440.         Print("Current aliases:\n");
  441.         count := Count(aliases);
  442.         while count ~= 0 do
  443.         count := count - 1;
  444.         alias := aliases[count];
  445.         Print("  ");
  446.         Print(alias@p_alName);
  447.         Print(" => ");
  448.         Print(alias@p_alAddress);
  449.         Print("\n");
  450.         od;
  451.     fi;
  452.     else
  453.     address := GetTail();
  454.     found := false;
  455.     if aliases ~= nil then
  456.         count := Count(aliases);
  457.         while count ~= 0 and not found do
  458.         count := count - 1;
  459.         alias := aliases[count];
  460.         if alias@p_alName == name then
  461.             found := true;
  462.         fi;
  463.         od;
  464.     fi;
  465.     Print("Alias \"");
  466.     Print(name);
  467.     Print("\" ");
  468.     if address = "" then
  469.         if found then
  470.         DelElement(aliases, alias);
  471.         ClearThing(alias);
  472.         Print("removed.\n");
  473.         else
  474.         Print("does not exist.\n");
  475.         fi;
  476.     else
  477.         if SubString(address, 0, 1) = "\"" then
  478.         address := SubString(address, 1, Length(address) - 2);
  479.         fi;
  480.         if found then
  481.         alias@p_alAddress := address;
  482.         Print("updated.\n");
  483.         else
  484.         if aliases = nil then
  485.             aliases := CreateThingList();
  486.             Me()@p_pEmailAliases := aliases;
  487.         fi;
  488.         alias := CreateThing(nil);
  489.         alias@p_alName := name;
  490.         alias@p_alAddress := address;
  491.         AddTail(aliases, alias);
  492.         Print("added.\n");
  493.         fi;
  494.     fi;
  495.     fi;
  496.     true
  497. corp;
  498.  
  499. VerbTail(g_email, "alias", mv_alias).
  500.  
  501. define tp_email proc emailEnter()status:
  502.     thing me;
  503.     action a;
  504.  
  505.     me := Me();
  506.     if Character(me@p_pName) = nil then
  507.     /* cannot do this stuff with machines! */
  508.     OPrint(FormatName(me@p_pName) + " will not enter.\n");
  509.     fail
  510.     else
  511.     a := SetCharacterInputAction(emailParse);
  512.     if a ~= nil then
  513.         me@p_pNSaveHandler := a;
  514.     fi;
  515.     me@p_pNSavePrompt := SetPrompt("telegram office> ");
  516.     continue
  517.     fi
  518. corp;
  519.  
  520. define tp_email proc emailExit()status:
  521.     thing me;
  522.  
  523.     me := Me();
  524.     ignore SetCharacterInputAction(me@p_pNSaveHandler);
  525.     ignore SetPrompt(me@p_pNSavePrompt);
  526.     me -- p_pEmailTo;
  527.     me -- p_pEmailSubject;
  528.     continue
  529. corp;
  530.  
  531. define tp_email r_emailRoom CreateThing(r_indoors).
  532. SetupRoom(r_emailRoom, "in the telegram office",
  533.     "In this room, the normal commands are replaced by another set which "
  534.     "is used to read, reply to, and send electronic mail letters. You can, "
  535.     "however use 'west' or 'out' to leave this room. Use 'help' to find out "
  536.     "how to use the service provided here.").
  537. r_emailRoom@p_rNoMachines := true.
  538. Connect(r_ne1, r_emailRoom, D_EAST).
  539. Connect(r_ne1, r_emailRoom, D_ENTER).
  540. ExtendDesc(r_ne1,
  541.     "To the east is a modest brick building of simple, but functional "
  542.     "architecture. A single wooden door without any windows opens directly "
  543.     "onto the sidewalk. Hanging by the door is a sign which reads \"Telegram "
  544.     "Office\". Small windows on each side of the door are firmly shut, and "
  545.     "each is covered by a green pull-down roller blind.").
  546. AddEastChecker(r_ne1, emailEnter, false).
  547. AddEnterChecker(r_ne1, emailEnter, false).
  548. AddWestChecker(r_emailRoom, emailExit, false).
  549. AddExitChecker(r_emailRoom, emailExit, false).
  550. Sign(r_ne1, "sign;hanging.door;sign,hanging,by,the", "","\"Telegram Office\"").
  551. Scenery(r_ne1,
  552.     "building;modest,brick."
  553.     "brick."
  554.     "door;wooden,windowless."
  555.     "blind;green,pull-down,pull,down,roller").
  556.  
  557. define tp_email TELEGRAM_OFFICE_ID NextEffectId().
  558. define tp_email proc drawEMailRoom()void:
  559.  
  560.     if not KnowsEffect(nil, TELEGRAM_OFFICE_ID) then
  561.     DefineEffect(nil, TELEGRAM_OFFICE_ID);
  562.     GSetImage(nil, "telegramOffice");
  563.     IfFound(nil);
  564.         GShowImage(nil, "", 0, 0, 160, 100, 0, 0);
  565.     Else(nil);
  566.         drawXXXXRoom("mail");
  567.     Fi(nil);
  568.     EndEffect();
  569.     fi;
  570.     CallEffect(nil, TELEGRAM_OFFICE_ID);
  571. corp;
  572.  
  573. RoomGraphics(r_emailRoom, "Telegram", "Office", NextMapGroup(), 0, 0,
  574.          drawEMailRoom).
  575.  
  576. unuse tp_email
  577. unuse t_streets
  578.